package com.magirard.project.manager.renderer 
{
	import com.adobe.utils.PerspectiveMatrix3D;
	import com.magirard.project.camera.BaseCamera;
	import com.magirard.project.entity.StaticMesh;
	import com.magirard.project.manager.stage.Stage2D;
	import flash.display.Stage;
	import flash.display.Stage3D;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DProgramType;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Matrix3D;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import flash.ui.Keyboard;
	
	public class RendererImpl extends EventDispatcher
	{
		private var mStage3dWidth:int;
		private var mStage3dHeight:int;
		private var mStage3d:Stage3D;
		private var mContext3d:Context3D;
		private var mEnableErrorChecking:Boolean = false;
		private var mProjectionMatrix:PerspectiveMatrix3D = new PerspectiveMatrix3D();
		
		private var mEntityList:Vector.<StaticMesh>;
		private var mModelViewProjection:Matrix3D = new Matrix3D();
		private var mCamera:BaseCamera;
		
		public function RendererImpl() 
		{
			mEntityList = new Vector.<StaticMesh>();
		}
		
		public function Init(aStage3dWidth:int, aStage3dHeight:int, aCamera:BaseCamera):void
		{
			mStage3dWidth = aStage3dWidth;
			mStage3dHeight = aStage3dHeight;
			mCamera = aCamera;
			
			mStage3d = Stage2D.stage3Ds[0];
			mStage3d.addEventListener(Event.CONTEXT3D_CREATE, OnContextInitialized);
			mStage3d.requestContext3D();
		}
		
		private function OnContextInitialized(aEvent:Event):void 
		{						
			mContext3d = (aEvent.target as Stage3D).context3D; 	

			if (mContext3d == null) 
			{
				return;
			}
			
			mContext3d.enableErrorChecking = mEnableErrorChecking;
			mContext3d.configureBackBuffer( mStage3dWidth, mStage3dHeight, 2, true);
			
			mProjectionMatrix.identity();
			mProjectionMatrix.perspectiveFieldOfViewRH(45.0, mStage3dWidth / mStage3dHeight, 0.01, 5000.0);
			
			dispatchEvent(aEvent);
		}
		
		public function AddEntity(aStaticMesh:StaticMesh):void
		{
			mEntityList.push(aStaticMesh);
			
		}
		
		public function get Context3d():Context3D
		{
			return mContext3d;
		}
		
		public function Render():void
		{
			mContext3d.clear(0, 0, 0); 
			

			
			for (var i:int = 0; i < mEntityList.length; i++)
			{
				mModelViewProjection.identity();
				mModelViewProjection.append(mEntityList[i].ModelMatrix);
				mModelViewProjection.append(mCamera.ViewMatrix);
				mModelViewProjection.append(mProjectionMatrix);
				mContext3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mModelViewProjection, true );
				mContext3d.setTextureAt(0, mEntityList[i].DiffuseTexture);
				mContext3d.setProgram (mEntityList[i].Shader.Program);
				mEntityList[i].Render();
			}
			
			mContext3d.present();
		}
		
	}

}